home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-10 | 28.1 KB | 901 lines | [TEXT/sade] |
- ##########################################################################################
- # Symbolic Application Debugging Environment 1.4
- #
- # copyright Apple Computer, Inc. 1987-1992
- # All rights reserved.
- #
- ##########################################################################################
- #
- # SADEStartup -- default OnEntry mechanism and support for source level debugging.
- #
-
- #
- # The following variables are used by the OnEntry and source & variable display mechanism.
- #
- define __SourceDbg__ := 1 # controls source vs. low-level debugging
- define __MaxWatchVars__ := 10 # maximum number of watched variables
- define __NumWatchVars__ := 0 # current number of watch variables
- define __WatchVar__[__MaxWatchVars__] # names of variables to watch
- define __MaxBreakifs__ := 10 # maximum number of conditional breaks
- define __BreakifAddr__[__MaxBreakifs__] # conditional break addresses
- define __BreakifCond__[__MaxBreakifs__] # conditional break conditions
- define __i__
- for __i__ := 1 to __MaxBreakifs__ do
- __BreakifAddr__[__i__] := 0
- end
- undefine __i__
-
- func __GetDirectoryFromFullPath__(FullPathName)
- define DirName := FullPathName
- define __i__
- for __i__ := length(DirName) downto 1 do
- if copy(DirName,__i__,1) = ':' then
- DirName := copy(DirName,1,__i__)
- return DirName
- end
- end
- return FullPathName
- end
-
- func __GetFileFromFullPath__(FullPathName)
- define FileName := FullPathName
- define __i__
- for __i__ := length(FileName) downto 1 do
- if copy(FileName,__i__,1) = ':' then
- FileName := copy(FileName, __i__+1, length(FileName))
- return FileName
- end
- end
- return FullPathName
- end
-
- define SADEDir := __GetDirectoryFromFullPath__(WorksheetWindow)
-
- # The "temporary" windows created by Sade are real files.
- # These are the register window, the value window, the stack window etc.
- # You can select the directory in which they accumulate. If you have a ramdisk,
- # override the next line in your SadeUserStartup.
- define __ScratchDir__ := concat(SADEDir, 'SADE Scratch:')
- macro __gValueWindow__ "concat(__ScratchDir__, 'Value')"
- macro __gRegisterWindow__ "concat(__ScratchDir__, 'Registers')"
- macro __gStackWindow__ "concat(__ScratchDir__, 'Stack Window')"
-
- # This sets the size of new windows [top, left, bottom, right]
- WindowSize New 0, 0, 200, 400
-
- # General error-handling proc.
- proc __Fail__(__ErrorString__)
- alert __ErrorString__
- redirect pop
- abort
- end
-
- # This macro is used by scripts below to check if there is a valid target.
- macro CheckNullTarget 'if processId = 0 then;alert "No process targeted.";abort;end'
-
- # This macro is used to check if the target is running.
- macro CheckRunningTarget 'if TargetRunning then;alert "Target is running.";abort;end'
- macro CheckNullOrRunningTarget 'CheckNullTarget;CheckRunningTarget'
-
- # This macro is used to see if we are at a "LINK A6, #$xxxx" instruction
- # (local variables are not valid until after the instruction has executed).
- macro PCIsAtLinkA6 '^ΔWord(ΔPC)^ = $4E56' # LINK opword = $4E56
-
- # If we haven't executed the LINK instruction, print a warning.
- proc CheckValidLocalVars
- CheckRunningTarget
- if PCIsAtLinkA6 then
- printf "Note: Parameters and local variables\naren't valid yet at this statement.\n"
- end
- end
-
- #
- # You may change the default values below to change how source level displays work.
- #
- define SourceInFront := 1 # controls whether source will be brought up as frontmost window
-
- # Set this if you want an alert on hitting a breakpoint.
- define Breakalert := 0 # controls breakpoint alert
-
- # Set __WantStackWindow__ to 1 if you want a live Stack window which updates every
- # time you step. Since this slows things down, you may prefer to leave it 0 and just
- # ask for a snapshot of the stack when you need to.
- define __WantStackWindow__ := 0 # controls stack display
-
- # Stack display -- the DoStack and DisplayStack procs
- proc DoStack
- redirect __gStackWindow__
- if PCIsAtLinkA6 then
- printf "Stack isn't valid yet at this statement.\n"
- else
- stack
- end
- redirect pop
- open __gStackWindow__
- end
-
- proc DisplayStack
- CheckNullTarget
- if TargetRunning then
- alert "The target is running. You must halt it to see its stack."
- abort
- end
- DoStack
- end
-
- proc ToggleWantStackWindow
- if __WantStackWindow__ = 0 then
- __WantStackWindow__ := 1
- open __gStackWindow__
- addmenu 'Variables' '!Live Stack Window' 'ToggleWantStackWindow' # '' is control-r (a checkmark)
- DisplayStack
- else
- __WantStackWindow__ := 0
- save __gStackWindow__
- close __gStackWindow__
- addmenu 'Variables' 'Live Stack Window' 'ToggleWantStackWindow'
- end
- end
-
- # Set __WantRegisterWindow__ to 1 if you want a live Registers window which updates every
- # time you step. Since this slows things down, you may prefer to leave it 0 and just
- # ask for a snapshot of the registers when you need to.
- define __WantRegisterWindow__ := 0 # controls register display
-
- #
- # Register display -- the Registers and DisplayRegs procs
- #
- proc Registers # This definition must precede the proc DisplayRegs
- redirect __gRegisterWindow__
- printf ("D0: $%.8X\nD1: $%.8X\nD2: $%.8X\nD3: $%.8X\nD4: $%.8X\nD5: $%.8X\nD6: $%.8X\nD7: $%.8X\n\n",ΔD0,ΔD1,ΔD2,ΔD3,ΔD4,ΔD5,ΔD6,ΔD7)
- printf ("A0: $%.8X\nA1: $%.8X\nA2: $%.8X\nA3: $%.8X\nA4: $%.8X\nA5: $%.8X\nA6: $%.8X\nA7: $%.8X\n\n",ΔA0,ΔA1,ΔA2,ΔA3,ΔA4,ΔA5,ΔA6,ΔA7)
- printf ("PC: $%.8X\n\n",ΔPC)
- printf ("\tXNZVC\n")
- printf ("CCR\t%.5b\n",(ΔCCR & $1F))
- redirect pop
- end
-
- proc DisplayRegs # This definition must precede the proc ToggleWantRegisterWindow
- CheckNullOrRunningTarget
- if TargetRunning then
- alert "The target is running. You must halt it to see its registers."
- abort
- end
- Registers
- open __gRegisterWindow__
- # SizeWindow To 160,295 __gRegisterWindow__
- end
-
- proc ToggleWantRegisterWindow
- if __WantRegisterWindow__ = 0 then
- __WantRegisterWindow__ := 1
- addmenu 'Variables' '!Live Register Window' 'ToggleWantRegisterWindow' # '' is control-r (a checkmark)
- DisplayRegs
- open __gRegisterWindow__
- else
- __WantRegisterWindow__ := 0
- save __gRegisterWindow__
- close __gRegisterWindow__
- addmenu 'Variables' 'Live Register Window' 'ToggleWantRegisterWindow'
- end
- end
-
- #
- # You can set the Safety variable to 1 if you want SADE to be more careful
- # when stepping and breaking. The default setting slightly increases the
- # possibility of SADE crashing because of a memory stomper in user code,
- # but makes stepping and breaking ten times faster.
- #
- Safety := 0
-
- #
- # By default, BreakifNoSource is false. This allows SADE to step
- # through routines like LMODT and UDIVT. It also lets SADE step
- # through Object Pascal and MacApp method dispatch code. However,
- # if you have enabled symbolics for only a small portion of your
- # code and do a step into, it will appear that SADE has hung when
- # it is really single stepping through zillions of instructions.
- # The default setting of 0 supports MacApp and avoids mystery
- # breaks in LMODT. See the "SADE New User WorkSheet" for details.
- BreakifNoSource := 0
-
- proc ToggleBreakifNoSource
- if BreakifNoSource = 0 then
- BreakifNoSource := 1
- addmenu 'SourceCmds' '!Break if No Source' 'ToggleBreakifNoSource' # '' is control-r (a checkmark)
- else
- BreakifNoSource := 0
- addmenu 'SourceCmds' 'Break if No Source' 'ToggleBreakifNoSource'
- end
- end
-
- #
- # By default, __StopBeforeStatic__ is 0. This makes SADE step to
- # main.(0) when an application is launched. If you set it to 1, SADE
- # will give you control before any code in the app is run. You can then
- # place breakpoints at your static constructors before you proceed.
- #
- define __StopBeforeStatic__ := 0
-
- proc ToggleStopBeforeStatic
- if __StopBeforeStatic__ = 0 then
- __StopBeforeStatic__ := 1
- addmenu 'File' '!Stop Before Constructor' 'ToggleStopBeforeStatic'
- else
- __StopBeforeStatic__ := 0
- addmenu 'File' 'Stop Before Constructor' 'ToggleStopBeforeStatic' # '' is control-r (a checkmark)
- end
- end
-
- proc ToggleSourceDbg
- if __SourceDbg__ = 0 then
- __SourceDbg__ := 1
- deletemenu 'SourceCmds' '!Asm [vs. Source] Debugging' # '' is control-r (a checkmark)
- addmenu 'SourceCmds' '!Source [vs. Asm] Debugging' 'ToggleSourceDbg' # '' is control-r (a checkmark)
- else
- __SourceDbg__ := 0
- deletemenu 'SourceCmds' '!Source [vs. Asm] Debugging' # '' is control-r (a checkmark)
- addmenu 'SourceCmds' '!Asm [vs. Source] Debugging' 'ToggleSourceDbg' # '' is control-r (a checkmark)
- end
- end
-
- # Return true if the 1st character of __theStr__ is in [A-Z,a-z,_]
- func IsAlpha(__theStr__)
- define __theChar__ := copy(__theStr__, 1, 1)
- if (__theChar__ >= 'a') and (__theChar__ <= 'z') then
- return 1
- end
- if (__theChar__ >= 'A') and (__theChar__ <= 'Z') then
- return 1
- end
- if (__theChar__ = '_') then
- return 1
- end
- return 0
- end
-
- # Add a backquote to the selected name to evaluate it as a program variable.
- func QualifiedVariableName(__VarName__)
- if copy(__VarName__, 1, 1) = '`' then
- return __VarName__
- end
- if IsAlpha(__VarName__)
- return concat('`', __VarName__)
- end
- return __VarName__
- end
-
- func CheckedEval(__Expression__, __ErrorString__)
- define __EvaledExpr__
- __EvaledExpr__ := eval(__Expression__,'???')
- if typeof(__EvaledExpr__) = 'PString' then
- if __EvaledExpr__ = '???' THEN
- __Fail__(concat(__ErrorString__, __Expression__))
- elseif copy(__EvaledExpr__, 1, 21) = '### eval syntax error' then
- __Fail__(concat('Expression syntax error: ', __Expression__))
- end
- end
- return __EvaledExpr__
- end
-
- # Print a variable's name and value, with linebreaks as necessary.
- proc PrettyPrintValue(__TheVarName__)
- # __TheVarName__ := QualifiedVariableName(__TheVarName__)
- define __EvaledVar__ := CheckedEval(__TheVarName__, 'Undefined/Out of scope: ')
- if sizeof(__EvaledVar__) > 4 then
- printf "%s =\n%t\n", __TheVarName__, __EvaledVar__
- else
- printf "%s = %t\n", __TheVarName__, __EvaledVar__
- end
- end
-
- # Print a variable's name and its value in hex, with linebreaks as necessary.
- proc PrettyPrintValueInHex(__TheVarName__)
- # __TheVarName__ := QualifiedVariableName(__TheVarName__)
- define __EvaledVar__ := CheckedEval(__TheVarName__, 'Undefined/Out of scope: ')
- if typeof(__EvaledVar__) = 'PString' then
- printf "Printing strings as hex values does not work well.\n"
- end
- if sizeof(__EvaledVar__) > 4 then
- printf "%s = Can not print non-integral objects as hex values.\n",__TheVarName__
- return
- else
- printf "%s = $%X\n", __TheVarName__, __EvaledVar__
- end
- end
-
- proc PrettyPrintValueNoalert(__TheVarName__)
- __TheVarName__ := QualifiedVariableName(__TheVarName__)
- define __EvaledVar__ := eval(__TheVarName__, '???')
- if typeof(__EvaledVar__) = 'PString' THEN
- if __EvaledVar__ = '???' THEN
- Printf "%s = Undefined/Out of scope\n", __TheVarName__
- return
- elseif copy(__EvaledVar__, 1, 21) = '### eval syntax error' then
- Printf "%s = Expression syntax error\n", __TheVarName__
- return
- end
- end
- if sizeof(__EvaledVar__) > 4 then
- printf "%s =\n%t\n", __TheVarName__, __EvaledVar__
- else
- printf "%s = %t\n", __TheVarName__, __EvaledVar__
- end
- end
-
- # Display the watch variables.
- proc DisplayWatchVars
- define __i__
- redirect concat(__ScratchDir__, "Variable Watch")
- CheckValidLocalVars
- for __i__ := 1 to __NumWatchVars__ do
- PrettyPrintValueNoalert(__WatchVar__[__i__])
- end
- redirect pop
- open behind concat(__ScratchDir__, "Variable Watch")
- end
-
- #••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
- #
- # Entry handling -- the StandardEntry proc
- #
- macro kSEProcessLoaded '65'
- macro kSETrace '51'
- macro kSEAddressBreak '58'
- macro kSESADEKeyInterrupt '55'
- macro kSEProcessHalted '8194'
- macro kSEMemoryProtectFault '66'
-
- func GetErrorString()
- define __errCause__ := ''
- if Exception = kSETrace then
- __errCause__ := "Instruction trace"
- elseif Exception = kSEAddressBreak then
- __errCause__ := "Address Break encountered"
- elseif Exception = 50 then
- __errCause__ := "Trap Break encountered"
- elseif (Exception = kSESADEKeyInterrupt) | (Exception = 13) then
- __errCause__ := "Program interrupted"
- elseif (Exception = kSEProcessHalted) then
- __errCause__ := "Process Halted"
- elseif Exception = 1 then
- __errCause__ := "Bus Error"
- elseif Exception = 2 then
- __errCause__ := "Address Error"
- elseif Exception = 3 then
- __errCause__ := "Illegal instruction encountered"
- elseif Exception = 4 then
- __errCause__ := "Divide by zero encountered"
- elseif Exception = 5 then
- __errCause__ := "CHK exception (array index out of range) encountered"
- elseif Exception = 6 then
- __errCause__ := "TRAPV or TRAPcc instruction encountered"
- elseif Exception = 7 then
- __errCause__ := "Privilege Violation"
- elseif Exception = 63 then
- __errCause__ := "Internal non-fatal error! You may be able to proceed..."
- elseif Exception = 64 then
- __errCause__ := "Internal fatal error! Please kill the target process!"
- elseif Exception = kSEProcessLoaded then
- __errCause__ := "Initial program break encountered"
- elseif Exception = kSEMemoryProtectFault then
- __errCause__ := "Write to protected memory detected"
- elseif Exception = -490 then
- __errCause__ := "User Break encountered"
- elseif Exception = -491 then
- __errCause__ := concat ("∂"", ^PString(ΔSP^)^, "∂"")
- ΔSP := ΔSP+4;
- elseif Exception = -492 then
- __errCause__ := concat ("Execute message not implemented ∂"", ^PString(ΔSP^)^, "∂"") # currently no way to execute this from SADE!
- ΔSP := ΔSP+4;
- elseif Exception = -490 then
- __errCause__ := "User Break encountered"
- else
- __errCause__ := concat('Error number ', Exception)
- end
- return __errCause__
- end
-
- proc __BreakBehavior__(__errCause__)
- alert concat(__errCause__, ' at ', where(ΔPC))
- # Beep
- end
-
- proc __UserEntryBehavior__
- end
-
- proc StandardEntry
- __UserEntryBehavior__
-
- # if we are at the startup code for a C program, move ahead to main.(0)
- if Exception = kSEProcessLoaded then
- if __StopBeforeStatic__ = 0 then
- if eval('main.(0)', '????') <> '????' then
- go til main.(0)
- stop
- end
- end
- end
-
- define __errCause__
- if __SourceDbg__ then
- if addrToSource(ΔPC, SourceInFront) and (Exception > 0) then
- if Exception <> kSETrace then
- __errCause__ := GetErrorString()
- if Breakalert then
- __BreakBehavior__(__errCause__)
- elseif (Exception <> kSEprocessLoaded) and (Exception <> kSEAddressBreak) and (Exception <> kSESADEKeyInterrupt) then
- alert concat(__errCause__, ' at ', where(ΔPC))
- end
- end
- else
- open WorksheetWindow
- __errCause__ := GetErrorString()
- printf "%s at ", __errCause__
- disasm ΔPC 1
- end
- else # Assembly mode
- open WorksheetWindow
- if Exception <> kSETrace then
- __errCause__ := GetErrorString()
- printf "%s at ", __errCause__
- end
- disasm ΔPC 1
- end
-
- if __NumWatchVars__ > 0 then
- DisplayWatchVars
- end
-
- if __WantStackWindow__ then
- DoStack
- end
-
- if __WantRegisterWindow__ then
- Registers
- end
- end
-
- OnEntry StandardEntry
-
-
- #
- # Macsbug equivalent command names for SADE
- # if you want these, remove the leading comments.
- # NOTE that these macros will be found before any program variables
- # of the same name!
- #
- # macro g "go"
- # macro il "disasm"
- # macro ip "disasm ΔPC-20 40"
- # macro br "break"
- # macro ht "heap totals"
- # macro hd "heap display"
- # macro atba "break all traps from applzone..applzone^"
- # macro mc "macro"
- # macro id "disasm"
- # macro sc "stack"
- # macro td "registers"
-
- #
- # Source Breakpoints
- #
- proc SetSourceBreak
- CheckNullTarget
- define __sourceBreak__ := sourceToAddr(activeWindow, 1)
- if typeof(__sourceBreak__) = 'PString' then
- alert concat('Cannot determine break address: ', __sourceBreak__)
- else
- break __sourceBreak__
- if not addrToSource(__sourceBreak__, 1) then # verify statement selection
- alert 'Able to set but not display breakpoint; SourcePath may not be set'
- end
- end
- end
-
- proc ProcessBreakIf # used by SetSourceBreakIf below
- define __i__
- define __addr__
- for __i__ := 1 to __MaxBreakifs__ do
- __addr__ := __BreakifAddr__[__i__]
- if __addr__ = ΔPC then
- if eval(__BreakifCond__[__i__]) then
- stop
- end
- end
- end
- end
-
- proc SetSourceBreakIf
- CheckNullTarget
- define __i__, __j__, __condition__, __EvaledCondition__
- define __sourceBreak__ := sourceToAddr(activeWindow, 1)
- if typeof(__sourceBreak__) = 'PString' then
- alert concat('Cannot determine break address: ', __sourceBreak__)
- abort
- end
- if (__condition__ := request('Condition to break on?')) = '_CANCEL_' then
- abort
- end
- if __condition__ = '' then
- alert 'No condition was specified; break not set'
- abort
- end
- # check for valid condition
- __EvaledCondition__ := eval(__condition__, '???')
- if typeof(__EvaledCondition__) = 'PString' then
- if __EvaledCondition__ = '???' then
- if not confirm('Variable not defined in current scope. Still set conditional break?') then
- abort
- end
- elseif copy(__EvaledCondition__, 1, 21) = '### eval syntax error' then
- alert concat('Cannot set conditional break. Expression syntax error: ', __condition__)
- abort
- end
- end
- # try to add to conditional break table
- for __i__ := 1 to __MaxBreakifs__ + 1 do
- if __i__ = (__MaxBreakifs__ + 1) then
- if not confirm('Conditional break table full; remove the oldest conditional break?') then
- abort
- end
- unbreak __BreakifAddr__[1] # remove the first installed
- for __j__ := 2 to __MaxBreakifs__ do # shift the others over
- __BreakifAddr__[__j__ - 1] := __BreakifAddr__[__j__]
- __BreakifCond__[__j__ - 1] := __BreakifCond__[__j__]
- end # remember the new one
- __BreakifAddr__[__MaxBreakifs__] := __sourceBreak__
- __BreakifCond__[__MaxBreakifs__] := __condition__
- leave
- elseif (__BreakifAddr__[__i__] = 0) | (__sourceBreak__ = __BreakifAddr__[__i__]) then
- __BreakifAddr__[__i__] := __sourceBreak__
- __BreakifCond__[__i__] := __condition__
- leave
- end
- end
- break __sourceBreak__ processBreakIf
- if not addrToSource(__sourceBreak__, 1) then # verify statement selection
- alert 'Able to set but not display breakpoint; SourcePath may not be set'
- end
- end
-
- proc __ClearBreakTable__
- define __i__
- for __i__ := 1 to __MaxBreakifs__ do
- __BreakifAddr__[__i__] := 0
- end
- end
-
- proc __UnbreakAll__
- CheckNullTarget
- Unbreak All
- __ClearBreakTable__
- end
-
- proc UnSetSourceBreak
- CheckNullTarget
- define __i__
- define __sourceBreak__ := sourceToAddr(activeWindow, 1)
- if typeof(__sourceBreak__) = 'PString' then
- alert concat('Cannot determine break address: ', __sourceBreak__)
- else
- unbreak __sourceBreak__
- for __i__ := 1 to __MaxBreakifs__ do # remove from Breakif table if present
- if __sourceBreak__ = __BreakifAddr__[__i__] then
- __BreakifAddr__[__i__] := 0
- leave
- end
- end
- if addrToSource(__sourceBreak__, 1) then; end # verify statement selection
- end
- end
-
- proc StepMenu
- CheckNullOrRunningTarget
- if __SourceDbg__ = 0 then
- step asm
- else
- step
- end
- end
-
- proc StepIntoMenu
- CheckNullOrRunningTarget
- if __SourceDbg__ = 0 then
- step asm into
- else
- step into
- end
- end
-
- proc StepOut
- CheckNullOrRunningTarget
- if PCIsAtLinkA6 then # if we are looking at a LINK instruction, A6 has not been
- go til (ΔA7)^ # set up but ΔA7 probably contains the right value
- else # if a LINK has already taken place,
- go til (ΔA6+4)^ # the return address is at ΔA6+4
- end
- end
-
- proc GoTil
- CheckNullOrRunningTarget
- define __sourceBreak__ := sourceToAddr(activeWindow, 1)
- if typeof(__sourceBreak__) = 'PString' then
- alert concat('Cannot determine break address: ', __sourceBreak__)
- else
- go til __sourceBreak__
- end
- end
-
- proc InWhatStatement
- CheckNullOrRunningTarget
- if not addrToSource(ΔPC, SourceInFront) then
- alert "Cannot find source for PC."
- end
- end
-
- proc ShowWhere
- define __loc__
- CheckNullTarget
- __loc__ := sourceToAddr(ActiveWindow, 1)
- if typeof(__loc__) = 'PString' then
- alert concat('Cannot determine address from source: ', __loc__)
- else
- alert concat('At ', where(__loc__))
- end
- end
-
- proc __CheckNullSelection__(__theSelection__)
- if length(__theSelection__) = 0 then
- __Fail__("Selection is zero-length.")
- end
- end
-
- proc ShowSource(__theSelection__)
- CheckNullTarget
- __CheckNullSelection__(__theSelection__)
- define __theFunc__ := eval(__theSelection__, '???')
- if typeof(__theFunc__) = 'PString' then
- if __theFunc__ = '???' then
- alert concat('"', __theSelection__, '" is not a function or procedure name which is known at this point.')
- else
- alert concat('"', __theSelection__, '" is not a function or procedure name.')
- end
- abort
- end
- if typeof(__theFunc__) <> 'CodeModule' then
- alert concat('"', __theSelection__, '" is not a function or procedure.')
- elseif not addrToSource(__theFunc__, 1) then
- alert concat('The source for "', __theSelection__, '" could not be found.')
- end
- end
-
- proc ShowValue(__theSelection__)
- CheckNullOrRunningTarget
- __CheckNullSelection__(__theSelection__)
- open __gValueWindow__
- redirect append __gValueWindow__
- CheckValidLocalVars
- PrettyPrintValue(__theSelection__)
- redirect pop
- end
-
- proc ShowValueInHex(__theSelection__)
- CheckNullOrRunningTarget
- __CheckNullSelection__(__theSelection__)
- redirect append __gValueWindow__
- CheckValidLocalVars
- PrettyPrintValueInHex(__theSelection__)
- redirect pop
- open __gValueWindow__
- end
-
- proc __CheckPointer__(__thePointer__)
- define __ErrorMessage__
- define __EvaledPointer__ := CheckedEval(__thePointer__, 'Undefined/Out of scope: ')
- define __TypeofPointer__ := typeof(__EvaledPointer__)
- if sizeof(__EvaledPointer__) <> 4 THEN
- # Not a pointer object
- __Fail__(concat(__thePointer__, " is not a pointer."))
- end
- if __TypeofPointer__ = '^Void' THEN
- __Fail__(concat('Can not dereference (void*) ', __thePointer__))
- end
- if __EvaledPointer__ = 0 then
- __ErrorMessage__ := concat('Cannot dereference NULL ', __thePointer__)
- __Fail__(__ErrorMessage__)
- end
- end
-
- proc ShowDereferencedValue(__theSelection__)
- CheckNullOrRunningTarget
- __CheckNullSelection__(__theSelection__)
- __theSelection__ := QualifiedVariableName(__theSelection__)
- __CheckPointer__(__theSelection__)
- ShowValue(concat(__theSelection__, '^'))
- end
-
- proc ShowDereferencedValueInHex(__theSelection__)
- CheckNullOrRunningTarget
- __CheckNullSelection__(__theSelection__)
- __theSelection__ := QualifiedVariableName(__theSelection__)
- __CheckPointer__(__theSelection__)
- ShowValueInHex(concat(__theSelection__, '^'))
- end
-
- proc AddWatchVar(__theSelection__)
- CheckNullOrRunningTarget
- __CheckNullSelection__(__theSelection__)
- define __EvaledExpr__
- if __NumWatchVars__ > (__MaxWatchVars__ - 1) then
- alert "Cannot add more watch variables"
- else
- __theSelection__ := QualifiedVariableName(__theSelection__)
- __EvaledExpr__ := eval(__theSelection__, '???')
- if typeof(__EvaledExpr__) = 'PString' then
- if copy(__EvaledExpr__, 1, 21) = '### eval syntax error' then
- alert concat('Cannot add watch variable. Expression syntax error: ', __theSelection__)
- return
- elseif __EvaledExpr__ = '???' then
- if not confirm(concat(__theSelection__, ' not defined at this time. Still add as watch variable?')) then
- return
- end
- end
- end
- __NumWatchVars__ := __NumWatchVars__ + 1
- __WatchVar__[__NumWatchVars__] := __theSelection__
- # Now refresh the display window
- DisplayWatchVars
- end
- end
-
-
- proc DeleteWatchVar(__theSelection__)
- CheckNullTarget
- __CheckNullSelection__(__theSelection__)
- define __i__, __found__ := 0
- __theSelection__ := QualifiedVariableName(__theSelection__)
- for __i__ := 1 to __NumWatchVars__ do
- if __found__ then
- __WatchVar__[__i__-1] := __WatchVar__[__i__]
- elseif __theSelection__ = __WatchVar__[__i__] then
- __found__ := 1
- end
- end
- if __found__ then
- __WatchVar__[__NumWatchVars__] := 0
- __NumWatchVars__ := __NumWatchVars__ - 1
- # Now refresh the display window
- DisplayWatchVars
- else
- alert concat('Cannot find watch variable "', __theSelection__, '" to delete')
- end
- end
-
- proc DeleteAllWatchVars
- __NumWatchVars__ := 0
- save concat(__ScratchDir__, "Variable Watch")
- close concat(__ScratchDir__, "Variable Watch")
- end
-
-
- proc SADEHelp(__theSelection__)
- define __HelpWindowName__ := concat(__ScratchDir__, "SADE_Info")
- redirect __HelpWindowName__
- printf "# Select a word and then choose the SADE Help menu item.\n"
- printf "# try: BuiltIns Commands Expressions Patterns\n"
- printf "# : Shortcuts Variables Basetypes <commandName>\n\n"
- #
- if __theSelection__ = '' then
- __theSelection__ := "Commands"
- end
- help expr(__theSelection__)
- redirect pop
- open __HelpWindowName__
- define __dummy__
- __dummy__ := selection(__HelpWindowName__, 0, 0)
- end
-
-
- #
- #
- # Killing or untargeting the target
- # Killing a target means to terminate it. Untargeting it, however, simply means for
- # SADE to stop treating it as a target. The semantics of untargeting are as follows:
- # if the target is running, it is left running. If it is suspended at a breakpoint,
- # it is restarted. If it is suspended due to a "hard" exception (e.g. a bus error),
- # it is killed.
- # Care is required in killing MPW tools. Since in debugging a tool SADE's target is
- # actually the MPW shell, the kill command will kill the shell as well as the tool.
- # To avoid this, the KillTool proc below will kill a suspended tool without killing
- # the shell. (KillTool won't kill a running tool.) The KillTarget proc checks the
- # type of the target and executes either Kill or KillTool as appropriate.
- #
-
- proc UnTarget
- Target ''
- __ClearBreakTable__
- end
-
- proc KillTool
- ΔPC := @µSYSRECOVER # set the pc to the shell's error recovery routine
- go
- end
-
- proc KillTarget
- if TargetIsMPWTool then
- KillTool
- else
- kill
- end
- __ClearBreakTable__
- __NumWatchVars__ := 0
- end
-
-
- #
- #
- # SADE menu initialization
- # Sets up SourceCmds and Variables menus, and adds Kill, Quit, and Help items
- # to the File menu.
- #
- #
-
- addmenu 'File' 'Stop Before Constructor' 'ToggleStopBeforeStatic'
- addMenu 'File' 'Kill' 'KillTarget'
- addMenu 'File' '(-' ''
-
- # The default quit menu saves all dirty files before quitting.
- # Use the commented-out form if you'd rather be prompted than save automatically.
-
- #addMenu 'File' 'Quit /Q' 'quit'
- addMenu 'File' 'Quit /Q' 'Save All;Quit'
-
- addMenu 'Find' '(-' ''
- addMenu 'Find' 'SADE Help/1' 'SADEHelp(selection(ActiveWindow))'
-
- addmenu 'SourceCmds' 'Break /B' 'SetSourceBreak'
- addmenu 'SourceCmds' 'Break if…/∫' 'SetSourceBreakIf'
- addmenu 'SourceCmds' 'Unbreak /U' 'UnSetSourceBreak'
- addmenu 'SourceCmds' 'Unbreak All' '__UnbreakAll__'
- addmenu 'SourceCmds' '(-' ''
- addmenu 'SourceCmds' 'Step /L' 'StepMenu'
- addmenu 'SourceCmds' 'Step Into /¬' 'StepIntoMenu' # '¬' is Opt-l
- addmenu 'SourceCmds' 'Step Out' 'StepOut'
- addmenu 'SourceCmds' '(-' ''
- addmenu 'SourceCmds' 'Go /P' 'go'
- addmenu 'SourceCmds' 'Go Til /π' 'GoTil'
- addmenu 'SourceCmds' '(-' ''
- addMenu 'SourceCmds' 'In What Statement? /I' 'InWhatStatement'
- addMenu 'SourceCmds' 'Statement Selected Is?' 'ShowWhere'
- addMenu 'SourceCmds' 'Show Selected Routine' 'ShowSource(selection(ActiveWindow))'
- addmenu 'SourceCmds' '(-' ''
- addmenu 'SourceCmds' 'Break if No Source' 'ToggleBreakifNoSource'
- addmenu 'SourceCmds' '!Source [vs. Asm] Debugging' 'ToggleSourceDbg' # '' is control-r (a checkmark)
-
- addmenu 'Variables' 'Show Value /√' 'ShowValue(selection(ActiveWindow))' # '√' is Opt-v
- addmenu 'Variables' 'Show Dereferenced Value /◊' 'ShowDereferencedValue(selection(ActiveWindow))' # '◊' is Opt-shift-v
- addmenu 'Variables' 'Show Value in Hex' 'ShowValueInHex(selection(ActiveWindow))'
- addmenu 'Variables' 'Show Dereferenced Value in Hex' 'ShowDereferencedValueInHex(selection(ActiveWindow))'
- addmenu 'Variables' '(-' ''
- addmenu 'Variables' 'Add Watch Variable' 'AddWatchVar(selection(ActiveWindow))'
- addmenu 'Variables' 'Delete Watch Variable' 'DeleteWatchVar(selection(ActiveWindow))'
- addmenu 'Variables' 'Delete All Watch Variables' 'DeleteAllWatchVars'
- addmenu 'Variables' '(-' ''
- addmenu 'Variables' 'Show Registers' 'DisplayRegs'
- addmenu 'Variables' 'Live Register Window' 'ToggleWantRegisterWindow'
- addmenu 'Variables' '(-' ''
- addmenu 'Variables' 'Show Stack' 'DisplayStack'
- addmenu 'Variables' 'Live Stack Window' 'ToggleWantStackWindow'
-
- #
- # Execute SADEUserStartup, where you can add to and modify the stuff supplied here.
- #
- # NOTE: The order in which SADE executes startup files is: 1. SadeStartup,
- # 2. SadeUserStartup, 3... Any SADE text file beginning with 'SadeUserStartup•',
- # in alphabetical order. So if you want to override behavior defined in ANY other
- # script, be sure to define it in a script named something like 'SadeUserStartup•zzz'
- # which will be executed last.
- #
- execute ':SadeUserStartup'
-